using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Reflection;
using System.Net;

namespace Christian.Helle.PocketNews.PocketPC
{
	public sealed class ErrorLog
	{
		private static readonly object syncRoot = new object();

		private static StreamWriter PrepareLogFile()
		{
			lock (syncRoot)
			{
				string file = string.Format("{0}\\Errors.txt",
							Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase));

				if (File.Exists(file))
				{
					FileInfo fi = new FileInfo(file);
					if (fi.Length > 100 * 1024)
					{
						fi.Delete();
					}
				}

				StreamWriter sw = new StreamWriter(file, true, Encoding.UTF8);
				return sw; 
			}
		}

		public static void AppendError(string source, string message, string stacktrace)
		{
			StreamWriter sw = null;

			try
			{
				sw = PrepareLogFile();

				sw.WriteLine(
				  string.Format(
					"-=-=-=-=-=--=-=-\n{0}:\n{1}\n\nSTACK TRACE:\n{2}\n",
					DateTime.Now,
					message,
					stacktrace));

				sw.Close();
			}
			catch (Exception e)
			{
				Debug.Assert(false, "Error saving error information to Errors.txt", e.Message);
			}
			finally
			{
				if (sw != null)
				{
					sw.Close();
				}
			}
		}

		public static void AppendError(string source, string message, string innerexception, string stacktrace)
		{
			StreamWriter sw = null;

			try
			{
				sw = PrepareLogFile();

				if (string.IsNullOrEmpty(innerexception))
				{
					sw.WriteLine(
						string.Format(
							"-=-=-=-=-=--=-=-\n{0}:\n{1}\n\nSTACK TRACE:\n{2}\n",
							DateTime.Now,
							message,
							stacktrace));
				}
				else
				{
					sw.WriteLine(
						string.Format(
							"-=-=-=-=-=--=-=-\n{0}:\n{1}\n\nINNER EXCEPTION:\n{2}\n\nSTACK TRACE:\n{3}\n",
								DateTime.Now,
								message,
								innerexception,
								stacktrace));
				}

				sw.Close();
			}
			catch (Exception e)
			{
				Debug.Assert(false, "Error saving error information to Errors.txt", e.Message);
			}
			finally
			{
				if (sw != null)
				{
					sw.Close();
				}
			}
		}

		public static void AppendWebException(string source, WebException exception)
		{
			StreamWriter sw = null;

			try
			{
				sw = PrepareLogFile();

				if (exception.InnerException == null && string.IsNullOrEmpty(exception.InnerException.Message))
				{
					sw.WriteLine(
						string.Format(
							"-=-=-=-=-=--=-=-\n{0}:\n{1}\n\nWEB EXCEPTION MESSAGE:\n{2}\n\nWEB EXCEPTION STATUS:\n{3}\n\nSTACK TRACE:\n{4}\n",
								DateTime.Now,
								exception.Message,
								GetWebExceptionStatus(exception),
								exception.StackTrace));
				}
				else
				{
					sw.WriteLine(
						string.Format(
							"-=-=-=-=-=--=-=-\n{0}:\n{1}\n\nWEB EXCEPTION MESSAGE:\n{2}\n\nWEB EXCEPTION STATUS:\n{3}\n\nINNER EXCEPTION\n{4}:\n\nSTACK TRACE:\n{5}\n",
								DateTime.Now,
								exception.Message,
								GetWebExceptionStatus(exception),
								exception.InnerException.Message,
								exception.StackTrace));
				}
			}
			catch (Exception e)
			{
				Debug.Assert(false, "Error saving error information to Errors.txt", e.Message);
			}
			finally
			{
				if (sw != null)
				{
					sw.Close();
				}
			}
		}

		private static string GetWebExceptionStatus(WebException e)
		{
			switch (e.Status)
			{
				case WebExceptionStatus.ConnectFailure:
					return "The remote service point could not be contacted at the transport level.";
				case WebExceptionStatus.ConnectionClosed:
					return "The connection was prematurely closed.";
				case WebExceptionStatus.KeepAliveFailure:
					return "The connection for a request that specifies the Keep-alive header was closed unexpectedly.";
				case WebExceptionStatus.NameResolutionFailure:
					return "The remote service point could not be contacted at the transport level.";
				case WebExceptionStatus.Pending:
					return "An internal asynchronous request is pending.";
				case WebExceptionStatus.PipelineFailure:
					return "The request was a piplined request and the connection was closed before the response was received.";
				case WebExceptionStatus.ProtocolError:
					return "The response received from the server was complete but indicated a protocol-level error. For example, an HTTP protocol error such as 401 Access Denied would use this status.";
				case WebExceptionStatus.ProxyNameResolutionFailure:
					return "The name resolver service could not resolve the proxy host name.";
				case WebExceptionStatus.ReceiveFailure:
					return "A complete response was not received from the remote server.";
				case WebExceptionStatus.RequestCanceled:
					return "The request was canceled, the System.Net.WebRequest.Abort() method was called, or an unclassifiable error occurred. This is the default value for System.Net.WebException.Status.";
				case WebExceptionStatus.SecureChannelFailure:
					return "An error occurred while establishing a connection using SSL.";
				case WebExceptionStatus.SendFailure:
					return "A complete request could not be sent to the remote server.";
				case WebExceptionStatus.ServerProtocolViolation:
					return "The server response was not a valid HTTP response.";
				case WebExceptionStatus.Timeout:
					return "No response was received during the time-out period for a request.";
				case WebExceptionStatus.TrustFailure:
					return "A server certificate could not be validated.";
				case WebExceptionStatus.Success:
					return "No error was encountered.";
				default:
					return "No error was encountered.";
			}
		}
	}
}
